#include "event_loop.h"
#include <iostream>
#include "acceptor.h"

using namespace as::snet;

EventLoop::EventLoop()
{
    m_eventList.reserve(1024);
    m_workPoller = std::make_unique<Poller>(*this);
}

void EventLoop::start(int workthreadNum)
{
    m_state = WORK_STATE_WORKING;
    for(int i = 0; i < workthreadNum; ++i)
    {
        m_workThread.emplace_back(&EventLoop::work_run, this);
    }
}

void EventLoop::stop()
{
    m_state = WORK_STATE_READY_STOP;
    m_cv.notify_all();
    for(auto &thread : m_workThread)
    {
        while(1)
        {
            if (thread.joinable())
            {
                thread.join();
                break;
            }
        }
    }

    m_state = WORK_STATE_STOP;
    std::cout << "event loop stop ok" << std::endl;
}

void EventLoop::run()
{
    while(m_state == WORK_STATE_WORKING)
    {
        //_sleep(1000);
    }
    std::cout << "event loop run break" << std::endl;
}

void EventLoop::work_run()
{
    //todo reserver vector
    while(m_state == WORK_STATE_WORKING)
    {
        EventVec tmp; 
        {
            std::unique_lock<std::mutex> ul(m_lock);
            m_cv.wait(ul, [this]()
            {
                return this->m_hasEvent or m_state != WORK_STATE_WORKING; 
            });
            m_hasEvent = false;
            tmp.swap(m_eventList);
        }

        for(const auto &ev : tmp)
        {
            if(ev.m_event_type == event_base::EV_READ)
            {
                handle_read(ev.m_fd);             
            }
            else if(ev.m_event_type == event_base::EV_WRITE)
            {
                handle_write(ev.m_fd);
            }
            else if(ev.m_event_type == event_base::EV_ACCEPT_UPDATE)
            {
                if(m_state != WORK_STATE_WORKING)
                    continue;

                Acceptor *acc = reinterpret_cast<Acceptor*>(ev.m_handle_ptr);
                if(acc)
                {
                    acc->update();
                    this->add_event(ev);
                }
            }
        }

    }

    std::cout << std::this_thread::get_id() << std::endl;
    // std::cout << "event loop break " << std::this_thread::get_id() << std::endl;
}

void EventLoop::add_event(const event_base &ev)
{
    m_lock.lock();
    m_eventList.emplace_back(ev);
    m_hasEvent = true;
    m_lock.unlock();

    m_cv.notify_one();
}

void EventLoop::handle_read(socket_fd fd)
{
    
}

void EventLoop::handle_write(socket_fd fd)
{

}

void EventLoop::on_poll(void *key, void *ev)
{

}

